using System;
using System.Text;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;

using Framework;

namespace SchemaMonitor
{
    //Collection Class (Customisable half)
    public partial class CSignatureList
    {
        #region Filters
        public CSignatureList Manual { get { return GetByDiscoveryId(EDiscovery.Manual); } }
        public CSignatureList Auto   { get { return GetByDiscoveryId(EDiscovery.Auto); } }
        public CSignatureList System { get { return GetByDiscoveryId(EDiscovery.System); } }
        public CSignatureList GetByDiscoveryId(EDiscovery d) { return GetByDiscoveryId((byte)d); }

        public CSignature GetByApiPath(string p)
        {
            var list = new CSignatureList(1);
            foreach (var i in this)
                if (i.Type.TypeApiPath == p)
                    return i;
            return null;
        }

        public List<string> NamesAndCounts
        {
            get
            {
                var list = new List<string>(this.Count);
                foreach (var i in this)
                    list.Add(CUtilities.NameAndCount(i.SigDescription, i.Types));
                return list;
            }
        }

        public List<string> Names
        {
            get
            {
                var list = new List<string>(this.Count);
                foreach (var i in this)
                    list.Add(i.SigDescription);
                return list;
            }
        }


        public CSignatureList GetByHash(CSignature s) { return GetByHash(s.SigHash); }
        public CSignatureList GetByHash(CSignature s, EDiscovery d) { return GetByDiscoveryId(d).GetByHash(s.SigHash); }

        public string Shortest
        {
            get
            {
                var s = string.Empty;
                foreach (var i in this)
                    if (s.Length == 0 || i.SigDescription.Length < s.Length)
                        s = i.SigDescription;
                return s;
            }
        }

        #endregion

        #region Aggregation
        public bool IsDataset
        {
            get
            {
                foreach (var i in this.Auto)
                    if (i.SigDescription == "data" ||
                        i.SigDescription == "data,paging")
                        return true;
                return false;
            }
        }
        #endregion



        #region Cloning
        public CSignatureList Clone(CDataSrc target) //, int parentId)
        {
            //No Transaction
            if (target is CDataSrcRemote)
                return Clone(target, null); //, parentId);

            //Transaction
            using (IDbConnection cn = target.Local.Connection())
            {
                IDbTransaction tx = cn.BeginTransaction();
                try
                {
                    CSignatureList clone = Clone(target, tx); //, parentId);
                    tx.Commit();
                    return clone;
                }
                catch
                {
                    tx.Rollback();
                    throw;
                }
            }
        }
        public CSignatureList Clone(CDataSrc target, IDbTransaction txOrNull) //, int parentId)
        {
            CSignatureList list = new CSignatureList(this.Count);
            foreach (CSignature i in this)
                list.Add(i.Clone(target, txOrNull)); //, parentId));  *Child entities must reference the new parent
            return list;
        }
        #endregion
        
        #region Export to Csv
        //Web - Need to add a project reference to System.Web, or comment out these two methods
        public void ExportToCsv(HttpResponse response) { ExportToCsv(response, "Signatures.csv"); }
        public void ExportToCsv(HttpResponse response, string fileName)
        {
            CDataSrc.ExportToCsv(response, fileName); //Standard response headers
            StreamWriter sw = new StreamWriter(response.OutputStream);
            ExportToCsv(sw);
            sw.Flush();
            response.End();
        }

        //Non-web
        public void ExportToCsv(string filePath)
        {
            StreamWriter sw = new StreamWriter(filePath);
            ExportToCsv(sw);
            sw.Close();
        }

        //Logic
        protected void ExportToCsv(StreamWriter sw)
        {
            string[] headings = new string[] {"SigHash", "SigTypeId", "SigDiscoveryId", "SigDescription", "SigCreated"};
            CDataSrc.ExportToCsv(headings, sw);
            foreach (CSignature i in this)
            {
                object[] data = new object[] {i.SigHash, i.SigTypeId, i.SigDiscoveryId, i.SigDescription, i.SigCreated};
                CDataSrc.ExportToCsv(data, sw);
            }
        }
        #endregion



        #region Members
        private CDiscoveryList _discoverys;
        private List<byte> _discoveryIds;

        private CTypeList _types;
        private List<int> _typeIds;
        #endregion 

        #region Resolve Associative table (and sort)
        public CDiscoveryList Discoverys
        {
            get
            {
                if (_discoverys == null)
                {
                    lock (this)
                    {
                        if (null == _discoverys)
                        {
                            _discoverys = new CDiscoveryList(this.Count);
                            foreach (CSignature i in this)
                                if (i.Discovery != null)
                                    _discoverys.Add(i.Discovery);
                            _discoverys.Sort();
                        }
                    }
                }
                return _discoverys;
            }
        }
        public CDiscoveryList RemainingDiscoverys(string search)
        {
            CDiscoveryList temp = new CDiscoveryList(CDiscovery.Cache.Search(search));
            temp.Remove(this.Discoverys);
            return temp;
        }

        public CTypeList Types
        {
            get
            {
                if (_types == null)
                {
                    lock (this)
                    {
                        if (null == _types)
                        {
                            _types = new CTypeList(this.Count);
                            foreach (CSignature i in this)
                                if (i.Type != null)
                                    _types.Add(i.Type);
                            _types.Sort();
                        }
                    }
                }
                return _types;
            }
        }
        public CTypeList RemainingTypes(string search)
        {
            CTypeList temp = new CTypeList(CType.Cache.Search(search));
            temp.Remove(this.Types);
            return temp;
        }
        #endregion

        #region Resolve/Isolate PKs
        public List<byte> DiscoveryIds
        {
            get
            {
                if (null == _discoveryIds)
                {
                    lock (this)
                    {
                        if (null == _discoveryIds)
                        {
                            _discoveryIds = new List<byte>(this.Count);
                            foreach (CSignature i in this)
                                _discoveryIds.Add(i.SigDiscoveryId);
                        }
                    }
                }
                return _discoveryIds;
            }
        }
        public List<int> TypeIds
        {
            get
            {
                if (null == _typeIds)
                {
                    lock (this)
                    {
                        if (null == _typeIds)
                        {
                            _typeIds = new List<int>(this.Count);
                            foreach (CSignature i in this)
                                _typeIds.Add(i.SigTypeId);
                        }
                    }
                }
                return _typeIds;
            }
        }
        #endregion



        public new void Add(CSignature item)
        {
            if (null != _index)
            {
                string k = Key(item.SigHash, item.SigTypeId);
                if (!_index.ContainsKey(k))
                    _index[k] = item;
            }
            _indexByDiscoveryId = null;
            _indexByHash = null;
            _indexByTypeId = null;
            base.Add(item);
        }

    }
}
